﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;

namespace NPuzzles_dynamiczne_kontrolki
{
    class MyPictureBoxesContainer
    {
        private MyPictureBox[] _PictureBoxesContainer;
        private Image _WholePicture;
        private int _PoziomTrudnosci;
        private Image _LastPicture;

        public MyPictureBoxesContainer(Image wimage, int lvl)
        {
            this._PictureBoxesContainer = new MyPictureBox[lvl * lvl];
            this._WholePicture = wimage;
            this._PoziomTrudnosci = lvl;
        }

        public void CreatePuzzle()
        {
            int maxrange = this._PoziomTrudnosci * this._PoziomTrudnosci;

            this._PictureBoxesContainer = new MyPictureBox[maxrange];

            Bitmap bm = new Bitmap(new Bitmap(this._WholePicture));
            System.Drawing.Imaging.PixelFormat pixformat = bm.PixelFormat;
            Rectangle current;

            int puzzlesize = Form1.ActiveForm.Size.Height / this._PoziomTrudnosci;
            int puzzlewidthfrompicture = this._WholePicture.Width / this._PoziomTrudnosci;
            int puzzleheightfrompicture = this._WholePicture.Height / this._PoziomTrudnosci;

            for (int i = 0; i < this._PoziomTrudnosci; i++)
            {
                for (int j = 0; j < this._PoziomTrudnosci; j++)
                {
                    Point puzzlestart = new Point(j * puzzlewidthfrompicture, i * puzzleheightfrompicture);
                    Point picturestart = new Point(j * puzzlesize, i * puzzlesize);
                    int n = Make2Dto1D(i, j, this._PoziomTrudnosci);
                    current = new Rectangle(puzzlestart.X, puzzlestart.Y, puzzlewidthfrompicture, puzzleheightfrompicture);

                    this._PictureBoxesContainer[n] = new MyPictureBox(n);
                    this._PictureBoxesContainer[n].Location = picturestart;
                    this._PictureBoxesContainer[n].SizeMode = PictureBoxSizeMode.StretchImage;
                    this._PictureBoxesContainer[n].Width = puzzlesize;
                    this._PictureBoxesContainer[n].Height = puzzlesize;
                    this._PictureBoxesContainer[n].Image = (Image)bm.Clone(current, pixformat);

                    this._PictureBoxesContainer[n].wcisniety += new pbklik(clik);

                    Form1.ActiveForm.Controls.Add(this._PictureBoxesContainer[n]);

                    //---------------------------------------------------------------------------------------------------------
                }
            }
        }

        private int Make2Dto1D(int i, int j, int lvl)
        {
            return i * lvl + j;
        }

        private void clik(int id)
        {
            this.MakeMove(id) ;
        }

        public void RandomizePuzzle()
        {
            Random rand = new Random();

            for (int i = 1; i < this._PictureBoxesContainer.Length - 1; i++)
            {
                int nr = rand.Next(i + 1);
                if (i != nr) swap(i, nr);
            }
            this.HideLastPicture();

        }

        private void swap(int n, int k)
        {
            MyPictureBox temp = new MyPictureBox();
            temp.Location= this._PictureBoxesContainer[n].Location;
            temp.currentid = this._PictureBoxesContainer[n].currentid;

            this._PictureBoxesContainer[n].Location = this._PictureBoxesContainer[k].Location;
            this._PictureBoxesContainer[k].Location = temp.Location;

            this._PictureBoxesContainer[n].currentid = this._PictureBoxesContainer[k].currentid;
            this._PictureBoxesContainer[k].currentid = temp.currentid;
            /*
            string msg = "";
            foreach (MyPictureBox ms in this._PictureBoxesContainer)
            {
                msg += ms.currentid + " " + ms.doceloweid + " ";
            }
            MessageBox.Show(msg);
             */
        }

        private void HideLastPicture()
        {
            int szerokoscpuzzla = this._WholePicture.Width / this._PoziomTrudnosci;
            int wysokoscpuzzla = this._WholePicture.Height / this._PoziomTrudnosci;
            Rectangle rc = new Rectangle(0, 0, szerokoscpuzzla, wysokoscpuzzla);
            Bitmap bit = new Bitmap(szerokoscpuzzla, wysokoscpuzzla);
            Graphics g = Graphics.FromImage((Image)bit);
            SolidBrush sb = new SolidBrush(Color.AntiqueWhite);
            g.FillRectangle(sb, rc);

            this._LastPicture = this._PictureBoxesContainer[this._PictureBoxesContainer.Length - 1].Image;
            this._PictureBoxesContainer[this._PictureBoxesContainer.Length - 1].Image = bit;
        }

        public void MakeMove(int nr)
        {
            int lewysasiad = (nr % this._PoziomTrudnosci) - 1;
            int prawysasiad = (nr + 1) % this._PoziomTrudnosci;
            int gornysasiad = nr - this._PoziomTrudnosci;
            int dolnysasiad = nr + this._PoziomTrudnosci;
            int docid = this._PictureBoxesContainer.Length-1;


            string msg = "";
            foreach (MyPictureBox ms in this._PictureBoxesContainer)
            {
                msg += ms.currentid + " " + ms.doceloweid + "   ";
            }
            MessageBox.Show(msg);

            int nb = FindNeighbour(nr - 1);
            if (lewysasiad >= 0 && this._PictureBoxesContainer[nb].doceloweid == docid) 
            {
                swap(nr, nb);
                //MessageBox.Show("lewy");
                return;
            }

            nb = FindNeighbour(nr + 1);
            if (prawysasiad > 0 && this._PictureBoxesContainer[nb].doceloweid == docid)
            {
                swap(nr, nb);
                //MessageBox.Show("prawy");
                return;
            }

            nb = FindNeighbour(gornysasiad);
            if (gornysasiad >= 0 && this._PictureBoxesContainer[nb].doceloweid == docid)
            {
                swap(nr, nb);
                //MessageBox.Show("gorny");
                return;
            }

            nb = FindNeighbour(dolnysasiad);
            if (dolnysasiad < this._PictureBoxesContainer.Length && this._PictureBoxesContainer[nb].doceloweid == docid)
            {
                swap(nr, nb);
                //MessageBox.Show("dolny");
                return;
            }
        }

        private int FindNeighbour(int nrsasiada)
        {
            for (int i = 0; i < this._PictureBoxesContainer.Length; i++)
            {
                if (this._PictureBoxesContainer[i].currentid == nrsasiada) return i;
            }
            return 0;
        }
    }
    
}
